/*
 * @Date: 2024-02-06 14:07:59
 * @LastEditors: lyx
 * @LastEditTime: 2024-03-20 18:47:07
 * @FilePath: \taro-template3\src\components\ChatItem\index.tsx
 * @Description: 对话项
 */
import React from 'react';
import { View } from "@tarojs/components";
import styles from "./index.module.scss";
import showdownHighlight from "showdown-highlight";
import showdown from "showdown";
import "highlight.js/styles/vs2015.css";
import cName from "classnames";
import MsgQuickAction from "../MsgQuickAction";
import RecommendationProblem from "../RecommendationProblem";
import { useEffect, useState, useRef, useContext, useMemo, useCallback } from "react";
import { IChatItemProps } from "./type";
import { CHAT_ROLE } from "@/utils/chat";
import Typed from 'typed.js';
import { ChatContext } from "@/pages/index/hooks/store";
import { useUpdateEffect } from "ahooks";
import { Recommended } from "@/pages/index/hooks/type";
import { IconFont } from "@nutui/icons-react-taro";
import chatGptIconIcon from "@/assets/images/chat/chatGptIcon.png";
import userIcon from "@/assets/images/chat/user.png";
import Taro from "@tarojs/taro";
import { render, unmountComponentAtNode } from '@tarojs/react';
import supGptCodePlugin from "./plugin";
import { debounce } from 'lodash';
import ChatEcharts from "@/packageA/components/ChatEcharts";
import CtxexpParser from "ctxexp-parser";

interface FeatureItemType {
  type: ChatFeatureType,
  id: string,
  domId: string,
  content: string
}
const hljs = require('highlight.js');
const md = require('markdown-it')({
  html: true,
  linkify: true,
  typographer: true,
  highlight: function (str: string, lang: string) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '<pre class="hljs"><code>' +
          hljs.highlight(lang, str, true).value +
          '</code></pre>';
      } catch (__) { }
    }

    return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
  }
});
md.use(supGptCodePlugin);
const DOMParser = require('xmldom').DOMParser;

function ChatItem(props: IChatItemProps) {
  const { index, key, chatItem, handleLongPress } = props;
  const { qList, viewContent, isLoading } = useContext(ChatContext);
  const [renderDom, setRenderDom] = useState<React.ReactDOM>(null);
  const converter = new showdown.Converter({
    extensions: [showdownHighlight],
  });
  const el = useRef<any>(null);
  const typedRef = useRef<any>(null);
  const featureRef = useRef<FeatureItemType[]>([])

  const [showAction, setShowAction] = useState(true);

  const showActionLog = () => {
    setShowAction(!showAction)
  }

  const { actions, role, recommended, content, id, msgId, parentMsgId } = useMemo(() => {
    return {
      actions: chatItem?.messageBody?.actions ?? [],
      role: chatItem?.messageBody?.contents?.[0]?.role ?? CHAT_ROLE.error,
      recommended: chatItem?.messageBody?.recommended ?? {} as Recommended,
      content: chatItem?.messageBody?.contents?.[0]?.content || '未找到相关答案，您可以重新提问',
      parentMsgId: chatItem?.parentMsgId ?? '',
      msgId: chatItem?.msgId ?? '',
      id: chatItem?.id ?? '',
    }
  }, [chatItem]);

  // 是否展示生成中的文案
  const showRenderContentText = useMemo(() => {
    return role === CHAT_ROLE.assistant && viewContent.id === msgId && isLoading
  }, [role, viewContent, msgId, isLoading]);

  // 是否展示取消生成的文案
  const showRenderCancelContentText = useMemo(() => {
    return role === CHAT_ROLE.assistant && viewContent.id === msgId && viewContent.cancelAsk
  }, [role, viewContent, msgId]);

  const renderMd = (loading = true) => {
    const defaultHtml = loading ? '<view class="chat-answer-load">答案正在生成中...</view>' : '未找到相关答案，您可以重新提问'
    if (el) {
      el!.current!.innerHTML = defaultHtml;
    }
  }

  const parseMd = (mdStr: string): Promise<{
    resultHtml: string,
    featureArr: FeatureItemType[]
  }> => {
    return new Promise((reslove) => {
      // const result = converter.makeHtml(mdStr);
      const result = md.render(mdStr);
      const regex = /(<supgptcode\s+[^>]*>[\s\S]*?<\/supgptcode>)/g;
      const arr: FeatureItemType[] = []
      const replacedString = result.replace(regex, (match: any, openTag: any, content: any, closeTag: any) => {
        // 创建一个新的 DOMParser 实例
        const parser = new DOMParser();
        // 解析标签字符串为 DOM 文档
        const doc = parser.parseFromString(match, 'text/html');
        // 获取解析后的标签元素
        const tagElement = doc.firstChild as any;
        // const tagElement = doc.body.firstChild as any;

        // 获取标签元素的内容
        const matchText = match.match(/<supgptcode[^>]*>([\s\S]*?)<\/supgptcode>/);
        const textContent = matchText && matchText[1] ? matchText[1] : '';
        const codeType = tagElement.getAttribute('data-codeType');
        const codeId = tagElement.getAttribute('data-codeId');
        const resId = chatItem.id;
        const idStr = `chat-${codeType}-${chatItem.msgId}-${resId}`
        const classStr = `chat-${codeType}-block`
        arr.push({
          type: codeType,
          id: codeId,
          domId: idStr,
          content: textContent
        })
        // 在这里根据需要替换为不同的元素或内容
        const replacement = `<view id='${idStr}' class='${classStr}'></view>`;
        return replacement;
      });
      // console.log('replacedString', replacedString)
      reslove({
        resultHtml: replacedString,
        featureArr: arr
      })
    })
  }

  const renderEcharts = (data: FeatureItemType) => {
    console.log('renderEcharts data', data);
    const featureData = chatItem;
    const chartDataCxt = chatItem?.messageBody?.chartData ?? {};
    const chartData = chartDataCxt && chartDataCxt[data.id] ? chartDataCxt[data.id] : []
    console.log('fn chartData', chartData);
    // const fn = new Function(`var data = ${typeof chartData === 'string' ? chartData : JSON.stringify(chartData)};${data.content}return option;`);
    // console.log('fn', fn);
    // let resOptions = fn();
    // TODO: js 语法解析
    let handleFun = `var data = ${typeof chartData === 'string' ? chartData : JSON.stringify(chartData)};${data.content}return option;`
    const $ = {
      fn() {
        return `var data = 1; return data;`;
      },
    };
    const exp = `$.fn()`;
    // let resOptions = new CtxexpParser($, exp).exec();
    let resOptions: any = {
      "title": {
        "left": "center",
        "textStyle": {
          "fontSize": 18,
          "color": "black"
        }
      },
      "tooltip": {
        "trigger": "axis",
        "axisPointer": {
          "type": "shadow"
        }
      },
      "legend": {
        "top": "30",
        "data": [
          "电（/滨化集团/基础化工生产基地/生产一部/化工氯碱)"
        ]
      },
      "grid": {
        "top": "18%",
        "left": "3%",
        "right": "4%",
        "bottom": "3%",
        "containLabel": true
      },
      "xAxis": {
        "type": "category",
        "data": [
          "2024-03-12 00:00:00",
          "2024-03-13 00:00:00",
          "2024-03-14 00:00:00",
          "2024-03-15 00:00:00",
          "2024-03-16 00:00:00",
          "2024-03-17 00:00:00",
          "2024-03-17 23:59:59"
        ]
      },
      "yAxis": [
        {
          "type": "value"
        }
      ],
      "series": [
        {
          "name": "电（/滨化集团/基础化工生产基地/生产一部/化工氯碱)",
          "type": "line",
          "yAxisIndex": 0,
          "data": [
            {
              "value": 15558390.631301,
              "unit": "KWh"
            },
            {
              "value": 15637501.758352,
              "unit": "KWh"
            },
            {
              "value": 15602598.281695,
              "unit": "KWh"
            },
            {
              "value": 15606631.765026,
              "unit": "KWh"
            },
            {
              "value": 15575167.450365,
              "unit": "KWh"
            },
            {
              "value": 15975479.262729,
              "unit": "KWh"
            },
            {
              "value": 16102153.425452,
              "unit": "KWh"
            }
          ]
        }
      ]
    };
    console.log('renderEcharts resOptions', resOptions);

    resOptions = resOptions && typeof resOptions === 'object' ? resOptions : {}
    // setRenderDom(<ChatEcharts option={resOptions} />)
    setRenderDom(<ChatEcharts isPage={false} option={{
      "title": {
        "left": "center",
        "textStyle": {
          "fontSize": 18,
          "color": "black"
        }
      },
      "tooltip": {
        "trigger": "axis",
        "axisPointer": {
          "type": "shadow"
        }
      },
      "legend": {
        "top": "30",
        "data": [
          "电（/滨化集团/基础化工生产基地/生产一部/化工氯碱)"
        ]
      },
      "grid": {
        "top": "18%",
        "left": "3%",
        "right": "4%",
        "bottom": "3%",
        "containLabel": true
      },
      "xAxis": {
        "type": "category",
        "data": [
          "2024-03-12 00:00:00",
          "2024-03-13 00:00:00",
          "2024-03-14 00:00:00",
          "2024-03-15 00:00:00",
          "2024-03-16 00:00:00",
          "2024-03-17 00:00:00",
          "2024-03-17 23:59:59"
        ]
      },
      "yAxis": [
        {
          "type": "value"
        }
      ],
      "series": [
        {
          "name": "电（/滨化集团/基础化工生产基地/生产一部/化工氯碱)",
          "type": "line",
          "yAxisIndex": 0,
          "data": [
            {
              "value": 15558390.631301,
              "unit": "KWh"
            },
            {
              "value": 15637501.758352,
              "unit": "KWh"
            },
            {
              "value": 15602598.281695,
              "unit": "KWh"
            },
            {
              "value": 15606631.765026,
              "unit": "KWh"
            },
            {
              "value": 15575167.450365,
              "unit": "KWh"
            },
            {
              "value": 15975479.262729,
              "unit": "KWh"
            },
            {
              "value": 16102153.425452,
              "unit": "KWh"
            }
          ]
        }
      ]
    }} />)

  }

  const renderTable = (data: FeatureItemType) => {
    let tableData = {
      reportDataType: 'table',
      reportData: [],
    }
    const chartDataCxt = chatItem?.messageBody?.chartData ?? {};

    if (chartDataCxt[data.id]) {
      const sourceData = chartDataCxt[data.id];
      if (typeof sourceData === 'string') {
        tableData.reportData = JSON.parse(sourceData)
      } else {
        if (sourceData.reportDataType && sourceData.reportData) {
          tableData.reportDataType = sourceData.reportDataType
          if (sourceData.reportDataType === 'table') {
            tableData.reportData = sourceData.reportData[0] ? JSON.parse(sourceData.reportData[0]) : {}
          } else {
            tableData.reportData = sourceData.reportData
          }
        } else {
          tableData.reportData = sourceData
        }
      }
    }
    // const featureData = featureDataRef.current
    // const idStr = `chat-table-luckysheet-${featureData.msgId}-${data.id}`
    // featureTbleRef.current[idStr] = data
    // if (!featureData.tablePreview && !coverImgMap[idStr] && tableData.reportDataType === 'table' && Object.keys(tableData.reportData).length > 0) {
    //   addTask(featureData.msgId, idStr, tableData.reportData)
    // }
    // root.render(tableData.reportDataType === 'table' ? <ChatTable tableData={tableData.reportData} chatInfo={{
    //   msgId: featureData.msgId,
    //   dataId: data.id,
    // }} onRender={onRender} imgUrl={featureData.tablePreview || coverImgMap[idStr]}></ChatTable> : <div>
    //   <div>当前报表不存在</div>
    //   {
    //     !!tableData.reportData.length && <div>您可以问询以下报表{tableData.reportData.join('、')}</div>
    //   }
    // </div>)
  }

  const renderFeature = () => {
    featureRef.current.forEach((item) => {
      if (item.type === 'echarts') {
        console.log('渲染echart');
        renderEcharts(item)
      }
      else if (item.type === 'table') {
        renderTable(item)
      }
      //  else if (item.type === 'rctable') {
      //     renderRcTable(item)
      // } else if (item.type === 'topology') {
      //     renderTopology(item)
      // } else if (item.type === 'autoModelCalculate' || item.type === 'bottleneckAnalysis') {
      //     renderAutoModelCalculate(item)
      // }
    })
  }

  const renderFeatureCb = useCallback(debounce(() => {
    if (featureRef.current.length > 0) {
      renderFeature()
    }
  }, 1000), [])

  /**
   * @description: 渲染 回答
   * @param {string} str
   * @return {*}
   */
  const renderContentMd = (str: string) => {
    parseMd(str).then((res) => {
      console.log('parseMd res==>', res);
      if (res.featureArr.length) {
        featureRef.current = res.featureArr;
        renderFeatureCb();
      }
      // onRender && onRender(false)
    })
  }

  useEffect(() => {
    if (showRenderContentText) {
      renderMd()
    } else if (showRenderCancelContentText) {
      console.log('showRenderCancelContentText==>');
      renderMd(false)
    }
  }, [showRenderContentText, showRenderCancelContentText])

  useUpdateEffect(() => {
    let typed: any = null;
    if (role === CHAT_ROLE.assistant && viewContent.id === msgId) {
      if (!isLoading) {
        // 展示打字机效果内容
        typed = new Typed(el.current, {
          strings: [content],
          typeSpeed: 50,
          onComplete: () => {
            // 由于打字机效果导致不能直接渲染出md, 所以在结束后重置 content
            el!.current!.innerHTML = converter.makeHtml(content)

          }
        });
      }
    }
    typedRef.current = typed;

  }, [role, content, msgId, viewContent, isLoading]);

  // console.log('viewContent', viewContent);

  useEffect(() => {
    if (role === CHAT_ROLE.assistant) {
      renderContentMd(content)
    }
  }, [content, role]);

  useEffect(() => {
    return () => {
      if (typedRef.current) {
        typedRef.current?.destroy?.();
      }
    };
  }, []);

  return (
    <View className={styles["chat"]}>
      {
        role === CHAT_ROLE.user ?
          <View
            key={key}
          >
            <View className={styles['message-wrapper']}>
              <View className={styles['icon']}>
                <IconFont
                  name={userIcon}
                  size="2rem"
                />
              </View>

              <View
                className={cName(styles["message"], styles["message_user"])}
                onLongPress={(e) => {
                  handleLongPress(e, chatItem);
                }}
              >
                {content}
              </View>
            </View>
          </View>
          :
          <View key={key}>
            <View className={styles['chat-wrapper']}>
              <View className={styles['message-wrapper']}>
                <View className={styles['icon']}>
                  <IconFont
                    name={chatGptIconIcon}
                    size="2rem"
                  />
                </View>

                <View className={styles['message-body']}>


                  <View
                    className={cName(styles["message"], styles["message_ai"])}
                    onLongPress={(e) => {
                      handleLongPress(e, chatItem);
                    }}
                  >
                    {
                      renderDom ? renderDom :
                        <View
                          id={`chat-md-${id}`}
                          ref={el}
                          dangerouslySetInnerHTML={{
                            __html: converter.makeHtml(content),
                          }}
                        ></View>
                    }

                    {/* // ! 不是初始化的回答  */}
                    {!!parentMsgId && (
                      <MsgQuickAction msgContent={chatItem} handleActionClick={showActionLog} />
                    )}
                  </View>

                  {/* 流程日志 */}
                  {
                    actions && !!actions.length && showAction &&
                    <View className={styles['answer-actions']}>
                      {
                        actions.map((item, index) => {
                          return (
                            <View className={styles['answer-actions-item']} key={index}>
                              <View className={styles['answer-actions-item-t']}>{item.actionName}:</View>
                              <View className={styles['answer-actions-item-c']}>{item.actionContent}</View>
                            </View>
                          )
                        })
                      }
                    </View>
                  }
                </View>
              </View>

            </View>

            {/* 推荐问题 */}
            {index === qList?.length - 1 &&
              (recommended?.chatId || recommended?.chatId === '') && recommended?.content?.length && (
                <RecommendationProblem
                  recommended={recommended}
                />
              )}
          </View>
      }
    </View>
  );
}

export default ChatItem;
